package qc.module.ehs.api.controller;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.Texts;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import qc.common.core.constants.QCAuthConstant;
import qc.common.core.constants.QCConstant;
import qc.common.core.exception.QCPromptException;
import qc.common.core.unify.QCUnifyReturnValue;
import qc.common.core.utils.DateUtil;
import qc.common.core.utils.QcAttachementFile;
import qc.common.core.utils.QcAttachementsUtil;
import qc.module.ehs.dto.report.EhsReportFileUpdateDto;
import qc.module.ehs.dto.troublecorrect.*;
import qc.module.ehs.entity.EhsHazardIdentify;
import qc.module.ehs.entity.EhsTroubleCorrect;
import qc.module.ehs.service.EhsHazardIdentifyService;
import qc.module.ehs.service.EhsTroubleCorrectService;
import qc.module.platform.dto.file.FileInfoDto;
import qc.module.platform.dto.file.FileSaveDto;
import qc.module.platform.dto.uac.UacUserInfoDto;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TroubleCorrectController
 * 隐患治理
 *
 * @author QuCheng Tech
 * @since 2024/11/7
 */
@RestController
@RefreshScope
@RequestMapping("/troublecorrect")
public class TroubleCorrectController {

    @Autowired
    private EhsTroubleCorrectService service;

    @Autowired
    private EhsHazardIdentifyService hazardIdentifyService;

    @Autowired
    HttpServletRequest request;

    @Autowired
    private RestTemplatePlatform restTemplatePlatform;

    /**
     * 自定义上传目录
     * file.update-path 自定义目录
     * 默认路径为：D://upload
     */
    @Value("${qucheng.upload.path:D://upload}")
    private String UPLOAD_PATH;

    /**
     * 自定义下载目录
     * file.update-path 自定义目录
     * 默认路径为：D://download
     */
    @Value("${qucheng.download.path:D://download}")
    private String DOWNLOAD_PATH;

    /**
     * 查询隐患治理
     *
     * @param condition 查询条件
     * @return List<EhsTroubleCorrectInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/7
     */
    @RequestMapping(value = "/query", method = {RequestMethod.POST, RequestMethod.GET})
    public List<EhsTroubleCorrectInfoDto> query(@RequestBody EhsTroubleCorrectQueryConditionDto condition) throws QCPromptException {
        return service.query(condition);
    }

    /**
     * 批量派单
     *
     * @param dto 批量派单DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCHeng Tech
     * @since 2024/11/7
     */
    @RequestMapping(value = "/batchdispatch", method = {RequestMethod.POST})
    public String batchDispatch(@RequestBody EhsTroubleCorrectBatchDispatchDto dto) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //根据token获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);

        return service.batchDispatch(dto, userInfo);
    }

    /**
     * 派单
     *
     * @param dto 派单DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCHeng Tech
     * @since 2024/11/7
     */
    @RequestMapping(value = "/dispatch", method = {RequestMethod.POST})
    public String dispatch(@RequestBody EhsTroubleCorrectDispatchDto dto) throws QCPromptException {
        HttpHeaders headers = new HttpHeaders();
        headers.add(QCAuthConstant.TOKEN_HEADER_KEY, request.getHeader(QCAuthConstant.TOKEN_HEADER_KEY));
        headers.add(QCAuthConstant.PROJECT_CODE_HEADER_KEY, request.getHeader(QCAuthConstant.PROJECT_CODE_HEADER_KEY));
        //根据token获取用户信息
        UacUserInfoDto userInfo = restTemplatePlatform.getUserInfo(headers);

        return service.dispatch(dto, userInfo);
    }

    /**
     * 整改
     *
     * @param dto 整改完成填写DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCHeng Tech
     * @since 2024/11/7
     */
    @RequestMapping(value = "/correct", method = {RequestMethod.POST})
    public String correct(@RequestBody EhsTroubleCorrectCompleteDto dto) throws QCPromptException {
        return service.correct(dto);
    }

    /**
     * 验收
     *
     * @param dto 验收DTO
     * @return 成功返回null，失败返回错误或提示信息
     * @author QuCHeng Tech
     * @since 2024/11/7
     */
    @RequestMapping(value = "/check", method = {RequestMethod.POST})
    public String check(@RequestBody EhsTroubleCorrectCheckDto dto) {
        return service.check(dto);
    }

    /**
     * 获取指定危险源的隐患治理记录
     *
     * @param id 危险源ID
     * @return List<EhsTroubleCorrectInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/11
     */
    @GetMapping("/hazard")
    public List<EhsTroubleCorrectInfoDto> getByHazardByParam(@RequestParam String id) {
        return service.getByHazard(id);
    }

    /**
     * 获取指定危险源的隐患治理记录
     *
     * @param id 危险源ID
     * @return List<EhsTroubleCorrectInfoDto>
     * @author QuCheng Tech
     * @since 2024/11/11
     */
    @GetMapping("/hazard/{id}")
    public List<EhsTroubleCorrectInfoDto> getByHazardByPath(@PathVariable String id) {
        return service.getByHazard(id);
    }

    /**
     * 获取指定隐患治理
     *
     * @param id 隐患治理ID
     * @return EhsTroubleCorrectInfoDto
     * @author QuCheng Tech
     * @since 2024/11/22
     */
    @GetMapping("/get")
    public EhsTroubleCorrectInfoDto getByParam(@RequestParam String id) {
        return service.get(id);
    }

    /**
     * 获取指定隐患治理
     *
     * @param id 隐患治理ID
     * @return EhsTroubleCorrectInfoDto
     * @author QuCheng Tech
     * @since 2024/11/22
     */
    @GetMapping("/get/{id}")
    public EhsTroubleCorrectInfoDto getByPath(@PathVariable String id) {
        return service.get(id);
    }

    /***
     * 对指定的隐患治理生成报告；不管是否已有报告文件，均进行1次生成报告；如原无报告文件生成后将报告文件ID进行赋值更新，如原已有报告文件重新生成并覆盖已有的文件（报告文件ID不更新）；
     *
     * @param id 隐患治理ID
     * @return 报告文件ID
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/generaterpt", method = {RequestMethod.GET, RequestMethod.POST})
    public int generateReportByParam(@RequestParam(required = true) String id) throws QCPromptException {
        return generateTroubleCorrectWord(id);
    }

    /***
     * 对指定的隐患治理生成报告；不管是否已有报告文件，均进行1次生成报告；如原无报告文件生成后将报告文件ID进行赋值更新，如原已有报告文件重新生成并覆盖已有的文件（报告文件ID不更新）；
     *
     * @param id 隐患治理ID
     * @return 报告文件ID
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/generaterpt/{id}", method = {RequestMethod.GET, RequestMethod.POST})
    public int generateReportByPath(@PathVariable(required = true) String id) throws QCPromptException {
        return generateTroubleCorrectWord(id);
    }

    /***
     *对指定的隐患治理上传报告，不管是否已存在报告文件；
     *
     * @param dto 更新隐患治理报告DTO
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/3/5
     */
    @RequestMapping(value = "/uploadreport", method = {RequestMethod.POST})
    public String uploadReport(@RequestBody EhsReportFileUpdateDto dto) {
        if (dto == null)
            return QCUnifyReturnValue.Warn("上传的隐患治理报告对象不能为空");
        if (StringUtils.isBlank(dto.getId()))
            return QCUnifyReturnValue.Warn("上传的隐患治理报告信息中隐患治理ID不能为空");
        if (dto.getFileid() < 0x1)
            return QCUnifyReturnValue.Warn("上传的隐患治理报告信息中报告文件ID无效");

        return service.updateReport(dto.getId(), dto.getFileid());
    }

    /***
     * 测试使用：输出隐患治理报告文件流
     *
     * @param id 隐患治理ID
     * @param response 响应
     * @return void
     * @author QuCheng Tech
     * @since 2025/3/6
     */
    @RequestMapping(value = "/output", method = {RequestMethod.GET, RequestMethod.POST}, produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
    @ResponseBody
    public void outputReportFileStream(@RequestParam(required = true) String id, HttpServletResponse response) throws QCPromptException {
        //根据隐患治理ID获取报告文件ID，如果没有报告文件先进行生成
        EhsTroubleCorrect troubleCorrectEntity = service.getEntity(id);
        if (troubleCorrectEntity == null)
            throw new QCPromptException("输出隐患治理报告文件流时指定的隐患治理信息不存在");
        int reportFileId = 0x0;//最终返回隐患治理对应的报告文件ID
        //如果已有报告文件ID，获取已经的文件ID
        if (troubleCorrectEntity.getRptid() != null && troubleCorrectEntity.getRptid().intValue() > 0x0)
            reportFileId = troubleCorrectEntity.getRptid().intValue();
        else
            reportFileId = generateTroubleCorrectWord(id);

        FileInfoDto fileInfo = restTemplatePlatform.getFileById(reportFileId);
        if (fileInfo == null)
            throw new QCPromptException("输出隐患治理报告文件流时获取到的报告文件信息不存在");

        String fileName = fileInfo.getName() + "." + fileInfo.getExtension();
        String fileFullPath = fileInfo.getPath() + QCConstant.ROUTE_SPLIT + fileName;

        //文件头信息从文件中读取并进行设置
        String fileType = new MimetypesFileTypeMap().getContentType(fileFullPath);
        System.out.println("fileType=" + fileType);
        // 设置contenttype，即告诉客户端所发送的数据属于什么类型
        response.setHeader("Content-type", fileType);
        // 设置显示下载的文件名,设置字符集是避免文件名中有中文时出现乱码
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(), StandardCharsets.ISO_8859_1));
        response.addHeader("Pargam", "no-cache");
        response.addHeader("Cache-Control", "no-cache");

        File file = new File(fileFullPath);
        long fileLength = file.length();
        response.addHeader("Content-Length", String.valueOf(fileLength));

        // 将文件写入输入流
        try (FileInputStream fileInputStream = new FileInputStream(file);
             BufferedInputStream inputStream = new BufferedInputStream(fileInputStream)) {
            //修改为使用分块读，每块读完后写入
            try (ServletOutputStream outputStream = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                outputStream.flush();
            } catch (OutOfMemoryError e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成word文件，将文件信息保存到文件信息表中，返回隐患治理对应的报告文件ID
     *
     * @param troubleCorrectId 隐患治理ID
     * @return int
     * @author QuCheng Tech
     * @since 2025/3/6
     */
    int generateTroubleCorrectWord(String troubleCorrectId) throws QCPromptException {
        if (StringUtils.isBlank(troubleCorrectId))
            throw new QCPromptException("生成隐患治理报告时指定的隐患治理ID不能为空");
        //存放要填充的数据
        Map<String, Object> datas = new HashMap<String, Object>();

        String generateWordFileName = "安全隐患整改通知单";
        //输出为文件，指定输出文件名
        String fileUploadPath = UPLOAD_PATH + QCConstant.ROUTE_SPLIT;
        String templateFileName = "安全隐患整改通知单-模板.docx";
        String fileDownloadPath = DOWNLOAD_PATH + QCConstant.ROUTE_SPLIT;
        String destFileName = generateWordFileName + ".docx";
        int reportFileId = 0x0;//最终返回隐患治理对应的报告文件ID

        EhsTroubleCorrect troubleCorrectEntity = service.getEntity(troubleCorrectId);
        if (troubleCorrectEntity == null)
            throw new QCPromptException("生成隐患治理报告时指定的隐患治理信息不存在");

        //如果已有报告文件ID，获取已经的文件ID
        if (troubleCorrectEntity.getRptid() != null && troubleCorrectEntity.getRptid().intValue() > 0x0)
            reportFileId = troubleCorrectEntity.getRptid().intValue();
        //文件名使用隐患标题
        destFileName = generateWordFileName + "-" + troubleCorrectEntity.getTitle() + ".docx";

        try {
            //文字信息
            //datas.put("文字信息", Texts.of("觉巴水电厂水情自动测报系统现场实施情况记录单").create());
            //图片信息
            //datas.put("图片信息", Pictures.ofLocal("D:/data/template/images/签名.png").create());

            //隐患的上报情况需要从危险源辨识记录表中提取         
            EhsHazardIdentify identifyEntity = hazardIdentifyService.getIdentifyEntityByHazardIdAndTime(troubleCorrectEntity.getHazardid(), troubleCorrectEntity.getTm());
            if (identifyEntity != null) {
                datas.put("检查单位", Texts.of(identifyEntity.getUnitname()).create());
                datas.put("检查时间", Texts.of(DateUtil.getDateString(identifyEntity.getTm())).create());
                datas.put("检查组人员", Texts.of(identifyEntity.getUsername()).create());
            }

            //存在问题及整改要求
            StringBuilder sb = new StringBuilder();
            if (StringUtils.isNotBlank(troubleCorrectEntity.getTitle()))
                sb.append(troubleCorrectEntity.getTitle() + "\n");
            if (StringUtils.isNotBlank(troubleCorrectEntity.getDescription()))
                sb.append(troubleCorrectEntity.getDescription() + "\n");
            if (StringUtils.isNotBlank(troubleCorrectEntity.getReqdescription()))
                sb.append(troubleCorrectEntity.getReqdescription() + "\n");
            if (sb.length() > 0x0)
                datas.put("存在问题及整改要求", Texts.of(sb.toString()).create());
            //问题的附件
            String troubleImageFileName = getImageFullName(troubleCorrectEntity.getAttachment());
            if (StringUtils.isNotBlank(troubleImageFileName))
                datas.put("问题照片", Pictures.ofLocal(troubleImageFileName).create());

            if (StringUtils.isNotBlank(troubleCorrectEntity.getCorrectdescription()))
                datas.put("整改情况", Texts.of(troubleCorrectEntity.getCorrectdescription()).create());
            //整改的附件
            //使用替换图片不改变图片原有格式和大小
            String correctImageFileName = getImageFullName(troubleCorrectEntity.getCorrectattachment());
            if (StringUtils.isNotBlank(correctImageFileName))
                datas.put("整改照片", Pictures.ofLocal(correctImageFileName).create());

            if (StringUtils.isNotBlank(troubleCorrectEntity.getCorrectsign())) {
                //签字的属性数据为对应签字图片id
                try {
                    int fileId = Integer.parseInt(troubleCorrectEntity.getCorrectsign());
                    try {
                        FileInfoDto fileinfo = restTemplatePlatform.getFileById(fileId);

                        if (fileinfo != null) {
                            String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();
                            datas.put("整改责任人签字", Pictures.ofLocal(fileFullName).create());
                        }
                    } catch (QCPromptException e) {
                        e.printStackTrace();
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }

            if (troubleCorrectEntity.getCorrectendtm() != null)
                datas.put("整改责任人签字日期", Texts.of(DateUtil.getDateString(troubleCorrectEntity.getCorrectendtm())).create());

            if (StringUtils.isNotBlank(troubleCorrectEntity.getCheckdescription()))
                datas.put("复查情况", Texts.of(troubleCorrectEntity.getCheckdescription()).create());
            if (StringUtils.isNotBlank(troubleCorrectEntity.getChecksign())) {
                //签字的属性数据为对应签字图片id
                try {
                    int fileId = Integer.parseInt(troubleCorrectEntity.getChecksign());
                    try {
                        FileInfoDto fileinfo = restTemplatePlatform.getFileById(fileId);

                        if (fileinfo != null) {
                            String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();
                            datas.put("复查人签字", Pictures.ofLocal(fileFullName).create());
                        }
                    } catch (QCPromptException e) {
                        e.printStackTrace();
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }
            if (troubleCorrectEntity.getChecktm() != null)
                datas.put("复查人签字日期", Texts.of(DateUtil.getDateString(troubleCorrectEntity.getChecktm())).create());

            // 获取模板中的所有标签
            //XWPFTemplate compile = XWPFTemplate.compile(UPLOAD_PATH + QCConstant.ROUTE_SPLIT + "安全隐患整改通知单-模板.docx");
            //compile.writeToFile(DOWNLOAD_PATH + QCConstant.ROUTE_SPLIT + destFileName);
            //测试使用
            //datas.put("检查单位", Texts.of("测试填写的检查单位").create());
            //datas.put("检查时间", Texts.of("2025年1月18日").create());
            //datas.put("检查组人员", Texts.of("张三、李四").create());
            //XWPFTemplate.compile("d://upload//安全隐患整改通知单-模板.docx").render(datas).writeToFile("d://download//" + destFileName);

            XWPFTemplate.compile(fileUploadPath + templateFileName).render(datas).writeToFile(fileDownloadPath + destFileName);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //保存文件信息表中的信息
        FileSaveDto reportFileInfo = new FileSaveDto();
        reportFileInfo.setId(reportFileId);
        reportFileInfo.setPath(fileDownloadPath + destFileName);
        //reportFileInfo.setTitle(destFileName);//与传入path中的文件名相同，可以不重复传入
        reportFileInfo.setSystem("ehs");
        reportFileInfo.setModule("TroubleCorrectReport");

        //调用平台接口保存文件信息
        int saveFileResultId = restTemplatePlatform.saveFileInfo(reportFileInfo);
        //如果已有的文件ID为0，将调用平台保存文件信息接口返回的文件ID赋值给返回的文件ID
        if (reportFileId == 0x0) {
            reportFileId = saveFileResultId;
            //将保存文件信息返回的文件ID更新到隐患治理表中的报告文件ID
            String updateReportResult = service.updateReport(troubleCorrectId, saveFileResultId);
            if (StringUtils.isNotBlank(updateReportResult))
                throw new QCPromptException(updateReportResult);
        }

        return reportFileId;
    }

    /***
     * 根据输入的附件或文件json字符串得到图片完整路径和名称
     *
     * @param jsonString 附件或文件json字符串
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2025/1/19
     */
    String getImageFullName(String jsonString) {
        if (StringUtils.isNotBlank(jsonString)) {
            QcAttachementFile[] files = QcAttachementsUtil.resolve(jsonString);
            if (files != null && files.length > 0x0) {
                //附件只显示1张图片，判断文件类型是图片显示第1张图片文件
                for (QcAttachementFile file : files) {
                    //要求文件ID和type不为空
                    if (file.id > 0x0 && StringUtils.isNotBlank(file.type)) {
                        if (StringUtils.equalsIgnoreCase(file.getType(), "jpg") || StringUtils.equalsIgnoreCase(file.getType(), "jpeg") || StringUtils.equalsIgnoreCase(file.getType(), "png")) {
                            //根据文件ID获取文件的完整路径和名称，调用platform中的接口
                            try {
                                FileInfoDto fileinfo = restTemplatePlatform.getFileById(file.id);

                                if (fileinfo != null) {
                                    String fileFullName = fileinfo.getPath() + QCConstant.ROUTE_SPLIT + fileinfo.getName() + "." + fileinfo.getExtension();

                                    return fileFullName;
                                }
                            } catch (QCPromptException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }

        return null;
    }
}
